package org.github.core.redis;

import com.fasterxml.jackson.databind.ObjectMapper;
import javax.annotation.Nonnull;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import static org.springframework.data.redis.serializer.RedisSerializer.string;

public class JsonRedisTemplate extends RedisTemplate<String, Object> {
    public JsonRedisTemplate(RedisConnectionFactory connectionFactory, ObjectMapper objectMapper) {
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);

        setDefaultSerializer(string());
        setStringSerializer(string());
        setKeySerializer(string());
        setHashKeySerializer(string());
        setValueSerializer(jsonRedisSerializer);
        setHashValueSerializer(jsonRedisSerializer);
        setConnectionFactory(connectionFactory);
        afterPropertiesSet();
    }

    @SuppressWarnings("unchecked")
    public <T> ValueOperations<String, T> valueOps() {
        return (ValueOperations<String, T>) opsForValue();
    }

    public <T> HashOperations<String, String, T> hashOps() {
        return opsForHash();
    }

    @SuppressWarnings("unchecked")
    public <T> ListOperations<String, T> listOps() {
        return (ListOperations<String, T>) opsForList();
    }

    @SuppressWarnings("unchecked")
    public <T> SetOperations<String, T> setOps() {
        return (SetOperations<String, T>) opsForSet();
    }

    @SuppressWarnings("unchecked")
    public <T> ZSetOperations<String, T> zsetOps() {
        return (ZSetOperations<String, T>) opsForZSet();
    }

    @Nonnull
    @Override
    protected RedisConnection preProcessConnection(@Nonnull RedisConnection connection, boolean existingConnection) {
        return new DefaultStringRedisConnection(connection);
    }
}
